#pragma once

#include "Socket.hpp"
#include "log.hpp"
#include "Daemon.hpp"
#include <signal.h>
#include <unistd.h>
#include <functional>
#include <string>
#include <cstring>
#include <cerrno>

extern Log lg;

//using func_t = std::function<std::string(std::string)>;
using func_t = std::function<std::string(std::string&)>;

class TcpServer
{
public:
    TcpServer(uint16_t port, func_t callback) :_port(port) ,_callback(callback) {}

    void Init()
    {
        _sock.Socket();
        _sock.Bind(_port);
        _sock.Listen();
    }

    void Start()
    {
        Daemon("/home/gy");
        //子进程你自己玩去把，我父进程不等你了
        signal(SIGCHLD, SIG_IGN);

        //防止服务端向客户端写时，客户端已经关闭了文件
        //这样写端有，读端关系有可能受到信号终止服务器
        signal(SIGPIPE, SIG_IGN);

        while(1)
        {
            std::string ClientIP;
            uint16_t ClientPort;
            // int sockid = _sock.Accept(ClientIP, ClientPort);
            int sockid = _sock.Accept(ClientIP, ClientPort);

            if(sockid < 0)
            {
                lg(Warning, "accept error");
                continue;
            }

            pid_t pid = fork();
            if(pid == 0)
            {
                //sleep(5);
                _sock.Close();
                char buffer[4096];
                std::string message;
                while(1)
                {
                    memset(buffer, 0, sizeof(buffer));
                    int size = read(sockid, buffer, sizeof(buffer) - 1);
                    if(size > 0)
                    {
                        buffer[size] = '\0';
                        message += buffer;

                        lg(Debug, "收到消息：\n%s", message.c_str());
                        std::string ret_message;
                        do
                        {
                            ret_message = _callback(message);
                            lg(Debug, "处理后消息：\n%s", message.c_str());
                            
                            int n = write(sockid, ret_message.c_str(), ret_message.size());
                            if(n < 0)
                            {
                                lg(Error, "write error, code:%d, msg:%s", errno, strerror(errno));
                                exit(-10);
                            }
                        }while(ret_message.size());
                    }
                    else if(size == 0) break;
                    else break;
                }
                exit(0);
            }

            //像管道一样关闭相应文件描述符
            close(sockid);

        }
    }

private:
    Sock _sock;
    uint16_t _port;
    func_t _callback;
};
